<?php

namespace qywxmsgsdk\Provider;

use qywxmsgsdk\Contract\ProviderInterface;
use qywxmsgsdk\Exception\FinanceSDKException;
use qywxmsgsdk\Exception\InvalidArgumentException;

abstract class AbstractProvider implements ProviderInterface
{
    /**
     * 获取会话解密记录数据
     * @param int      $seq      起始位置
     * @param int      $limit    限制条数
     * @param int $last_seq 最后一条SEQ
     * @param bool $is_debug true=开启DEBUG模式
     * @return array ...
     * @throws FinanceSDKException
     * @throws InvalidArgumentException
     */
    public function getDecryptChatData(int $seq, int $limit, int &$last_seq = 0, bool $is_debug = false): array
    {
        $last_seq = 0;//重置SEQ
        $config   = $this->getConfig();
        if (!isset($config['private_keys'])) {
            throw new InvalidArgumentException('缺少配置:private_keys[{"version":"private_key"}]');
        }
        $privateKeys = $config['private_keys'];
        $maxVer      = max(array_keys($privateKeys));
        if (!is_numeric($maxVer) || $maxVer <= 0) {
            throw new InvalidArgumentException('消息加密公钥版本号必须是正整数');
        }
        try {
            $response = json_decode($this->getChatData($seq, $limit), true) ?: [];
            if ($is_debug) {
                return $response;
            }
            if (!$response || !empty($response['errcode'])) {
                throw new FinanceSDKException($response['errmsg'] ?? '获取会话存档失败', $response['errcode'] ?? 0);
            }
            $newChatData = [];
            foreach ($response['chatdata'] as $i => $item) {
                $last_seq = $item['seq'] ?? 0;
                if ($item['publickey_ver'] > $maxVer) {
                    throw new FinanceSDKException('消息加密公钥版本号已过期', -500);
                }
                if (!isset($privateKeys[$item['publickey_ver']])) {
                    continue;
                }
                $decryptRandKey = '';
                openssl_private_decrypt(
                    base64_decode($item['encrypt_random_key']),
                    $decryptRandKey,
                    $privateKeys[$item['publickey_ver']],
                    OPENSSL_PKCS1_PADDING
                );
                if (!$decryptRandKey) {
                    throw new FinanceSDKException('消息存档密钥错误', -501);
                }
                $newChatData[$i]        = json_decode($this->decryptData($decryptRandKey, $item['encrypt_chat_msg']), true);
                $newChatData[$i]['seq'] = $item['seq'];
            }
            return $newChatData;
        } catch (\Exception $e) {
            throw new FinanceSDKException($e->getMessage(), $e->getCode());
        }
    }
}
